/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * analiseDWT.java
 *
 * Created on 21/06/2010, 15:05:23
 */
package Wavelet.DWT.Daubechies;

import jEDF.JEDF.JEDFGraph;
import jEDF.JEDF.Polysomnograph;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Rectangle;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import org.jdesktop.application.Action;

/**
 *
 * @author FoSa
 */
public class analiseDaubechies extends javax.swing.JFrame {

    /** Creates new form analiseDWT */
    public analiseDaubechies() {
        initComponents();
        polysomnograph = null;
    }

    public analiseDaubechies(Polysomnograph polysomnograph) {
        this.polysomnograph = polysomnograph;
        initComponents();
        jSpinner1StateChanged(null);
    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel1 = new javax.swing.JPanel();
        fase1 = new javax.swing.JPanel();
        fase2 = new javax.swing.JPanel();
        fase3 = new javax.swing.JPanel();
        jPanel2 = new javax.swing.JPanel();
        jSpinner1 = new javax.swing.JSpinner();
        jButton1 = new javax.swing.JButton();
        jButton2 = new javax.swing.JButton();
        jButton3 = new javax.swing.JButton();
        jScrollPane1 = new javax.swing.JScrollPane();
        jPanel3 = new javax.swing.JPanel();

        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(projetotcc2.ProjetoTCC2App.class).getContext().getResourceMap(analiseDaubechies.class);
        setTitle(resourceMap.getString("Form.title")); // NOI18N
        setAlwaysOnTop(true);
        setMinimumSize(new java.awt.Dimension(350, 50));
        setName("Form"); // NOI18N

        jPanel1.setVisible(false);
        jPanel1.setName("jPanel1"); // NOI18N
        jPanel1.setLayout(new java.awt.GridLayout(3, 1));

        fase1.setBackground(resourceMap.getColor("fase1.background")); // NOI18N
        fase1.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        fase1.setName("fase1"); // NOI18N

        javax.swing.GroupLayout fase1Layout = new javax.swing.GroupLayout(fase1);
        fase1.setLayout(fase1Layout);
        fase1Layout.setHorizontalGroup(
            fase1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 566, Short.MAX_VALUE)
        );
        fase1Layout.setVerticalGroup(
            fase1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 67, Short.MAX_VALUE)
        );

        jPanel1.add(fase1);

        fase2.setBackground(resourceMap.getColor("fase2.background")); // NOI18N
        fase2.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        fase2.setName("fase2"); // NOI18N

        javax.swing.GroupLayout fase2Layout = new javax.swing.GroupLayout(fase2);
        fase2.setLayout(fase2Layout);
        fase2Layout.setHorizontalGroup(
            fase2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 566, Short.MAX_VALUE)
        );
        fase2Layout.setVerticalGroup(
            fase2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 67, Short.MAX_VALUE)
        );

        jPanel1.add(fase2);

        fase3.setBackground(resourceMap.getColor("fase3.background")); // NOI18N
        fase3.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        fase3.setName("fase3"); // NOI18N

        javax.swing.GroupLayout fase3Layout = new javax.swing.GroupLayout(fase3);
        fase3.setLayout(fase3Layout);
        fase3Layout.setHorizontalGroup(
            fase3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 566, Short.MAX_VALUE)
        );
        fase3Layout.setVerticalGroup(
            fase3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 67, Short.MAX_VALUE)
        );

        jPanel1.add(fase3);

        jPanel2.setName("jPanel2"); // NOI18N

        jSpinner1.setModel(new javax.swing.SpinnerNumberModel(3, 0, 20, 1));
        jSpinner1.setName("jSpinner1"); // NOI18N
        jSpinner1.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                jSpinner1StateChanged(evt);
            }
        });

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(projetotcc2.ProjetoTCC2App.class).getContext().getActionMap(analiseDaubechies.class, this);
        jButton1.setAction(actionMap.get("amplmais")); // NOI18N
        jButton1.setText(resourceMap.getString("jButton1.text")); // NOI18N
        jButton1.setName("jButton1"); // NOI18N

        jButton2.setAction(actionMap.get("resetampl")); // NOI18N
        jButton2.setText(resourceMap.getString("jButton2.text")); // NOI18N
        jButton2.setName("jButton2"); // NOI18N

        jButton3.setAction(actionMap.get("amplmenos")); // NOI18N
        jButton3.setText(resourceMap.getString("jButton3.text")); // NOI18N
        jButton3.setName("jButton3"); // NOI18N

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, 82, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton1)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton2)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jButton3)
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jSpinner1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jButton1)
                    .addComponent(jButton2)
                    .addComponent(jButton3))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        jScrollPane1.setName("jScrollPane1"); // NOI18N

        jPanel3.setName("jPanel3"); // NOI18N
        jPanel3.setLayout(new java.awt.GridLayout(3, 1));
        jScrollPane1.setViewportView(jPanel3);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 570, Short.MAX_VALUE)
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 570, Short.MAX_VALUE)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(221, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, 214, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 293, Short.MAX_VALUE))
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jSpinner1StateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSpinner1StateChanged
        // TODO add your handling code here:

        jPanel3.removeAll();
        int num = Integer.parseInt(jSpinner1.getValue().toString());
        painel = new Painel[num];
        jPanel3.setLayout(new GridLayout(num, 1));
        for (int i = 0; i < painel.length; i++) {
            painel[i] = new Painel();
            jPanel3.add(painel[i]);
            painel[i].setBackground(Color.white);
        }

        this.repaint();

        draw2();
        repaint();
    }//GEN-LAST:event_jSpinner1StateChanged

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new analiseDaubechies().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JPanel fase1;
    private javax.swing.JPanel fase2;
    private javax.swing.JPanel fase3;
    private javax.swing.JButton jButton1;
    private javax.swing.JButton jButton2;
    private javax.swing.JButton jButton3;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JSpinner jSpinner1;
    // End of variables declaration//GEN-END:variables
    private JEDFGraph graph = null;
    private final Polysomnograph polysomnograph;
    private int startSecond = 0;
    private int duration = 0;
    private double startPosition = 0;
    private double endPosition = 0;
    private Painel[] painel;

    @Override
    public void paint(Graphics g) {
        super.paint(g);
//        Graphics gr = fase1.getGraphics();
        draw2();
    }

    @Override
    public void repaint() {
        super.repaint();
//        Graphics g = jPanel1.getGraphics();
        draw2();
    }

    private void drawData(JComponent comp, double[] data) {
        int[] x = new int[(int) comp.getWidth()];
        double height = SwingUtilities.calculateInnerArea(comp, new Rectangle()).getHeight();

        comp.setBackground(Color.WHITE);
        comp.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        double maior = 0;
        for (int i = 0; i < data.length; i++) {
            maior = maior > Math.abs(data[i]) ? maior : data[i];
        }

        double yoffset = (height / 2) / (graph.getSignal().getDigMax());

        for (int i = 0; i < x.length; i++) {
            x[i] = i;
        }

        int[] dataint = new int[data.length];
        for (int i = 0; i < data.length; i++) {
            dataint[i] = (int) (-data[i] * yoffset + (height / 2));
        }

        try {
            Graphics g1 = comp.getGraphics();
            g1.setColor(Color.BLUE);
            g1.drawPolyline(x, dataint, x.length);
        } catch (Exception e) {
        }
    }

    void draw2() {
        if (graph == null) {
            return;
        }
        try {

            if (duration < 0) {
                duration *= -1;
                startSecond -= duration;
            }

            short[] selectedData = graph.getSignal().getSelectedSignalData(startSecond, duration, startPosition, endPosition);

            if (selectedData.length == 0) {
                return;
            }

            double[] data = new double[selectedData.length];
            double[] databaixa = new double[selectedData.length];
            this.setSize(data.length, this.getHeight());
            jPanel3.setSize(data.length, jPanel3.getHeight());
            jPanel3.setBounds(jPanel3.getX(), jPanel3.getY(), data.length, jPanel3.getHeight());

            for (int i = 0; i < selectedData.length; i++) {
                data[i] = selectedData[i];
            }

//            int num = Integer.parseInt(jSpinner1.getValue().toString());
//            painel = new JPanel[num];
//            jPanel3.setLayout(new GridLayout(num, 1));
            for (int i = 0; i < painel.length; i++) {
//                painel[i] = new
//                jPanel3.add(painel[i]);
                databaixa = passaBaixa(data);
//                databaixa = passaBaixaConvolution(data);
                painel[i].setData(databaixa);
//                drawData(painel[i], databaixa);
//                data = passaAlta(data);
                data = passaAltaConvolution(data);
            }

//            Coif06 coif = new Coif06();
//            double[] novo = coif.forward(data);



//            jPanel3.setPreferredSize(new Dimension(novo.length, (int) (jPanel3.getHeight())));
//            jPanel3.setBounds(jPanel3.getX(), jPanel3.getY(), novo.length, (int) (jPanel3.getHeight()));

//            painel[0].setData(novo);

//            drawData(fase1, data);
//
//            data = passaAlta(data);
//            data = passaBaixa(data);
//
//            drawData(fase2, data);
//
//            data = passaAlta(data);
//            data = passaBaixa(data);
//
//            drawData(fase3, data);
//            repaint();
        } catch (NullPointerException nu) {
            nu.printStackTrace();
        }


    }

    public void setDataSource(JEDFGraph graph, int startSecond, int duration, double startPosition, double endPosition) {
        this.graph = (JEDFGraph) graph.clone();
        this.startSecond = startSecond;
        this.duration = duration;
        this.startPosition = startPosition;
        this.endPosition = endPosition;




        if (isVisible()) {
            repaint();
        } else {
//            setVisible(true);
        }
    }

    double[] passaAlta(double[] db) {
        if (db.length == 0) {
            return new double[0];
        }
//        y[i] := α * (y[i-1] + x[i] - x[i-1])

        double alfa = 0.5;
        double[] retorno = new double[db.length];

        retorno[0] = db[0];

        for (int i = 1; i < db.length; i++) {
            retorno[i] = alfa * (retorno[i - 1] + db[i - 1] + db[i]);
        }

        return retorno;
    }

    double[] passaAltaConvolution(double[] db) {
        if (db.length == 0) {
            return new double[0];
        }
        double[] filter = D20(); // box-car filter

        double[] result = new double[db.length + filter.length + 1];

// Set result to zero:
        for (int i = 0; i < result.length; i++) {
            result[i] = 0;
        }

// Do convolution:
        for (int i = 0; i < db.length; i++) {
            for (int j = 0; j < filter.length; j++) {
                result[i + j] = result[i + j] + db[i] * filter[j];
            }
        }

        return result;
    }

    double[] passaBaixaConvolution(double[] db) {
        if (db.length == 0) {
            return new double[0];
        }
        double[] filter = D20(); // box-car filter

        double[] result = new double[db.length + filter.length + 1];

// Set result to zero:
        for (int i = 0; i < result.length; i++) {
            result[i] = 0;
        }

// Do convolution:
        for (int i = 0; i < db.length; i++) {
            for (int j = 0; j < filter.length; j++) {
                result[i + j] = result[i + j] + db[i] * filter[j];
            }
        }

        return result;
    }

    double[] D6() {
        double[] filter = new double[6];

        filter[ 0] = 0.47046721;
        filter[ 1] = 1.14111692;
        filter[ 2] = 0.650365;
        filter[ 3] = -0.19093442;
        filter[ 4] = -0.12083221;
        filter[ 5] = 0.0498175;

        return filter;
    }

    double[] D20() {
        double[] filter = new double[20];

        filter[ 0] = 0.03771716;
        filter[ 1] = 0.26612218;
        filter[ 2] = 0.74557507;
        filter[ 3] = 0.97362811;
        filter[ 4] = 0.39763774;
        filter[5] = -0.35333620;
        filter[ 6] = -0.27710988;
        filter[ 7] = 0.18012745;
        filter[ 8] = 0.13160299;
        filter[ 9] = -0.10096657;
        filter[ 10] = -0.04165925;
        filter[ 11] = 0.04696981;
        filter[ 12] = 5.10043697e-3;
        filter[ 13] = -0.01517900;
        filter[ 14] = 1.97332536e-3;
        filter[ 15] = 2.81768659e-3;
        filter[ 16] = -9.69947840e-4;
        filter[ 17] = -1.64709006e-4;
        filter[ 18] = 1.32354367e-4;
        filter[ 19] = -1.875841e-5;

        return filter;
    }

    public double[] forward(double[] arrTime) {
        int _waveLength = 6; // minimal array size for transform

        double[] _coeffs = new double[_waveLength]; // can be done in static way also; faster?
        double[] _scales = new double[_waveLength]; // can be done in static way also; faster?

        double sqrt15 = Math.sqrt(15.);

        _scales[ 0] = 1.4142135623730951 * (sqrt15 - 3.) / 32.;
        _scales[ 1] = 1.4142135623730951 * (1. - sqrt15) / 32.;
        _scales[ 2] = 1.4142135623730951 * (6. - 2 * sqrt15) / 32.;
        _scales[ 3] = 1.4142135623730951 * (2. * sqrt15 + 6.) / 32.;
        _scales[ 4] = 1.4142135623730951 * (sqrt15 + 13.) / 32.;
        _scales[ 5] = 1.4142135623730951 * (9. - sqrt15) / 32.;

        _coeffs[ 0] = _scales[ 5]; //    h5
        _coeffs[ 1] = -_scales[ 4]; //  -h4
        _coeffs[ 2] = _scales[ 3]; //    h3
        _coeffs[ 3] = -_scales[ 2]; //  -h2
        _coeffs[ 4] = _scales[ 1]; //    h1
        _coeffs[ 5] = -_scales[ 0]; //  -h0

        double[] arrHilb = new double[arrTime.length];

        int k = 0;
        int h = arrTime.length >> 1;

        for (int i = 0; i < h; i++) {

            for (int j = 0; j < _waveLength; j++) {

                k = (i << 1) + j;
                if (k >= arrTime.length) {
                    k -= arrTime.length;
                }

                arrHilb[i] += arrTime[k] * _scales[j]; // low pass filter - energy
                arrHilb[i + h] += arrTime[k] * _coeffs[j]; // high pass filter - details

            } // wavelet

        } // h

        return arrHilb;
    } // forward

    double[] passaBaixa(double[] db) {
        if (db.length == 0) {
            return new double[0];
        }
//        y[i] := y[i-1] + α * (x[i] - y[i-1])

        double alfa = 0.5;
        double[] retorno = new double[db.length];

        retorno[0] = db[0];

        for (int i = 1; i < db.length; i++) {
            retorno[i] = retorno[i - 1] + alfa * (db[i] - retorno[i - 1]);
        }

        return retorno;
    }

    void setZoomPaineis(double zoom) {
        for (int i = 0; i < painel.length; i++) {
            painel[i].setZoom(zoom);
        }
    }

    @Action
    public void amplmais() {
        setZoomPaineis(painel[0].getZoom() * 1.2);

//        jPanel3.set
//        jPanel3.setPreferredSize(new Dimension(jPanel3.getWidth(), (int) (jPanel3.getHeight() * 1.5)));
//        jPanel3.setBounds(jPanel3.getX(), jPanel3.getY(), jPanel3.getWidth(), (int) (jPanel3.getHeight() * 1.5));
        repaint();
    }

    @Action
    public void amplmenos() {
        setZoomPaineis(painel[0].getZoom() / 1.2);
//        jPanel3.set
//        jPanel3.setPreferredSize(new Dimension(jPanel3.getWidth(), (int) (jPanel3.getHeight() / 1.5)));
//        jPanel3.setBounds(jPanel3.getX(), jPanel3.getY(), jPanel3.getWidth(), (int) (jPanel3.getHeight() / 1.5));
        repaint();
    }

    @Action
    public void resetampl() {
        setZoomPaineis(1);
//        jPanel3.setPreferredSize(new Dimension(jScrollPane1.getWidth(), jScrollPane1.getHeight() / 2));
//        jPanel3.setBounds(jPanel3.getX(), jPanel3.getY(), jScrollPane1.getWidth(), jScrollPane1.getHeight() / 2);
        repaint();
    }

    class Painel extends JPanel {

        double[] data;
        double zoom = 1;

        public void setData(double[] data) {
            this.data = data;
        }

        public void setZoom(double zoom) {
            this.zoom = zoom;
        }

        public double getZoom() {
            return zoom;
        }

        public Painel() {
            super();
        }

//        @Override
//        public void paint(Graphics g) {
//            super.paint(g);
//            Draw(g);
//        }
//        @Override
//        public void repaint() {
//            super.repaint();
//            Draw();
//        }
        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Draw(g);
        }

        void Draw() {
            Graphics g = this.getGraphics();
            Draw(g);
        }

        private void Draw(Graphics g) {
            if (data == null) {
                return;
            }
            int[] x = new int[(int) this.getWidth()];
            double height = SwingUtilities.calculateInnerArea(this, new Rectangle()).getHeight();

            this.setBackground(Color.WHITE);
            this.setBorder(javax.swing.BorderFactory.createEtchedBorder());

//            double maior = 0;
//            for (int i = 0; i < data.length; i++) {
//                maior = maior > Math.abs(data[i]) ? maior : data[i];
//            }

            double yoffset = zoom * (height / 2) / (graph.getSignal().getDigMax());

            for (int i = 0; i < x.length; i++) {
                x[i] = i;
            }

            int[] dataint = new int[data.length];
            for (int i = 0; i < data.length; i++) {
                dataint[i] = (int) ((-data[i] * yoffset + (height / 2)));
            }

//            try {
//                g.setColor(Color.BLUE);
//                g.drawPolyline(x, dataint, x.length);
//            } catch (Exception e) {
//            }


//            Coif06 coif = new Coif06();
//            double[] novo = coif.forward(data);
//            this.setSize(novo.length, this.getHeight());
//
//            x = new int[novo.length];
//            for (int i = 0; i < x.length; i++) {
//                x[i] = i;
//            }
//
//            dataint = new int[novo.length];
//            for (int i = 0; i < novo.length; i++) {
//                dataint[i] = (int) ((-novo[i] * yoffset + (height / 2)));
//            }

            try {
                g.setColor(Color.BLUE);
                g.drawPolyline(x, dataint, x.length);
            } catch (Exception e) {
            }
        }
    }
}
